/*  PCSX2 - PS2 Emulator for PCs
 *  Copyright (C) 2002-2020  PCSX2 Dev Team
 *
 *  PCSX2 is free software: you can redistribute it and/or modify it under the terms
 *  of the GNU Lesser General Public License as published by the Free Software Found-
 *  ation, either version 3 of the License, or (at your option) any later version.
 *
 *  PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE.  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along with PCSX2.
 *  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#define SPU2_CORE0 0x00000000
#define SPU2_CORE1 0x00000400

#define SPU2_VP(voice) ((voice)*16)
#define SPU2_VA(voice) ((voice)*12)

#define REG_VP_VOLL 0x0000  // Voice Volume Left
#define REG_VP_VOLR 0x0002  // Voice Volume Right
#define REG_VP_PITCH 0x0004 // Pitch
#define REG_VP_ADSR1 0x0006 // Envelope 1 (Attack-Decay-Sustain-Release)
#define REG_VP_ADSR2 0x0008 // Envelope 2 (Attack-Decay-Sustain-Release)
#define REG_VP_ENVX 0x000A  // Current Envelope
#define REG_VP_VOLXL 0x000C // Current Voice Volume Left
#define REG_VP_VOLXR 0x000E // Current Voice Volume Right

// .. repeated for each voice ..

#define REG_S_PMON 0x0180   // Pitch Modulation Spec.
#define REG_S_NON 0x0184    // Alloc Noise Generator
#define REG_S_VMIXL 0x0188  // Voice Output Mix Left  (Dry)
#define REG_S_VMIXEL 0x018C // Voice Output Mix Left  (Wet)
#define REG_S_VMIXR 0x0190  // Voice Output Mix Right (Dry)
#define REG_S_VMIXER 0x0194 // Voice Output Mix Right (Wet)

#define REG_P_MMIX 0x0198 // Output Spec. After Voice Mix
#define REG_C_ATTR 0x019A // Core X Attrib
#define REG_A_IRQA 0x019C // Interrupt Address Spec.

#define REG_S_KON 0x01A0  // Key On 0/1
#define REG_S_KOFF 0x01A4 // Key Off 0/1

#define REG_A_TSA 0x01A8 // Transfer starting address
#define REG__1AC 0x01AC  // Transfer data
#define REG__1AE 0x01AE
#define REG_S_ADMAS 0x01B0 // AutoDMA Status

// 1b2, 1b4, 1b6, 1b8, 1ba, 1bc, 1be are unknown

#define REG_VA_SSA 0x01C0  // Waveform data starting address
#define REG_VA_LSAX 0x01C4 // Loop point address
#define REG_VA_NAX 0x01C8  // Waveform data that should be read next

// .. repeated for each voice ..

#define REG_A_ESA 0x02E0   //Address: Top address of working area for effects processing
#define R_APF1_SIZE 0x02E4 // Feedback Source A
#define R_APF2_SIZE 0x02E8 // Feedback Source B
#define R_SAME_L_DST 0x02EC
#define R_SAME_R_DST 0x02F0
#define R_COMB1_L_SRC 0x02F4
#define R_COMB1_R_SRC 0x02F8
#define R_COMB2_L_SRC 0x02FC
#define R_COMB2_R_SRC 0x0300
#define R_SAME_L_SRC 0x0304
#define R_SAME_R_SRC 0x0308
#define R_DIFF_L_DST 0x030C
#define R_DIFF_R_DST 0x0310
#define R_COMB3_L_SRC 0x0314
#define R_COMB3_R_SRC 0x0318
#define R_COMB4_L_SRC 0x031C
#define R_COMB4_R_SRC 0x0320
#define R_DIFF_L_SRC 0x0324 // Some sources have R_DIFF_R_SRC and R_DIFF_L_SRC swapped ><
#define R_DIFF_R_SRC 0x0328
#define R_APF1_L_DST 0x032C
#define R_APF1_R_DST 0x0330
#define R_APF2_L_DST 0x0334
#define R_APF2_R_DST 0x0338
#define REG_A_EEA 0x033C // Address: End address of working area for effects processing (upper part of address only!)

#define REG_S_ENDX 0x0340 // End Point passed flag

#define REG_P_STATX 0x0344 // Status register?

// 0x346 .. 0x3fe are unknown (unused?)

// core 1 has the same registers with 0x400 added.
// core 1 ends at 0x746

// 0x746 .. 0x75e are unknown

// "Different" register area

#define REG_P_MVOLL 0x0760  // Master Volume Left
#define REG_P_MVOLR 0x0762  // Master Volume Right
#define REG_P_EVOLL 0x0764  // Effect Volume Left
#define REG_P_EVOLR 0x0766  // Effect Volume Right
#define REG_P_AVOLL 0x0768  // Core External Input Volume Left  (Only Core 1)
#define REG_P_AVOLR 0x076A  // Core External Input Volume Right (Only Core 1)
#define REG_P_BVOLL 0x076C  // Sound Data Volume Left
#define REG_P_BVOLR 0x076E  // Sound Data Volume Right
#define REG_P_MVOLXL 0x0770 // Current Master Volume Left
#define REG_P_MVOLXR 0x0772 // Current Master Volume Right

#define R_IIR_VOL 0x0774
#define R_COMB1_VOL 0x0776
#define R_COMB2_VOL 0x0778
#define R_COMB3_VOL 0x077A
#define R_COMB4_VOL 0x077C
#define R_WALL_VOL 0x077E
#define R_APF1_VOL 0x0780
#define R_APF2_VOL 0x0782
#define R_IN_COEF_L 0x0784
#define R_IN_COEF_R 0x0786

// values repeat for core1

// End OF "Different" register area

// SPDIF interface
#define SPDIF_OUT 0x07C0 // SPDIF Out: OFF/'PCM'/Bitstream/Bypass
#define SPDIF_IRQINFO 0x07C2
#define SPDIF_MODE 0x07C6
#define SPDIF_MEDIA 0x07C8   // SPDIF Media: 'CD'/DVD
#define SPDIF_PROTECT 0x07CC // SPDIF Copy Protection


/*********************************************************************
Core attributes (SD_C)
  bit 1         - Unknown (this bit is sometimes set)
  bit 2..3      - Unknown (usually never set)
  bit 4..5      - DMA related
  bit 6         - IRQ? DMA mode? wtf?
  bit 7         - effect enable (reverb enable)
  bit 8			- IRQ enable?
  bit 9..14     - noise clock
  bit 15        - mute
  bit 16        - reset

*********************************************************************/

#define SPDIF_OUT_OFF 0x0000    // no spdif output
#define SPDIF_OUT_PCM 0x0020    // encode spdif from spu2 pcm output
#define SPDIF_OUT_BYPASS 0x0100 // bypass spu2 processing

#define SPDIF_MODE_BYPASS_BITSTREAM 0x0002 // bypass mode for digital bitstream data
#define SPDIF_MODE_BYPASS_PCM 0x0000       // bypass mode for pcm data (using analog output)

#define SPDIF_MODE_MEDIA_CD 0x0800  // source media is a CD
#define SPDIF_MODE_MEDIA_DVD 0x0000 // source media is a DVD

#define SPDIF_MEDIA_CDVD 0x0200
#define SPDIF_MEDIA_400 0x0000

#define SPDIF_PROTECT_NORMAL 0x0000   // spdif stream is not protected
#define SPDIF_PROTECT_PROHIBIT 0x8000 // spdif stream can't be copied

/********************************************************************/

#define VOICE_PARAM_VOLL 0x0  // Voice Volume Left
#define VOICE_PARAM_VOLR 0x2  // Voice Volume Right
#define VOICE_PARAM_PITCH 0x4 // Pitch
#define VOICE_PARAM_ADSR1 0x6 // Envelope 1 (Attack-Delay-Sustain-Release)
#define VOICE_PARAM_ADSR2 0x8 // Envelope 2 (Attack-Delay-Sustain-Release)
#define VOICE_PARAM_ENVX 0xA  // Current Envelope
#define VOICE_PARAM_VOLXL 0xC // Current Voice Volume Left
#define VOICE_PARAM_VOLXR 0xE // Current Voice Volume Right

/********************************************************************/

#define VOICE_ADDR_SSA 0x0  // Waveform data starting address
#define VOICE_ADDR_LSAX 0x4 // Loop point address
#define VOICE_ADDR_NAX 0x8  // Waveform data that should be read next



// --------------------------------------------------------------------------------------
//  SPU2 Register Table LUT
// --------------------------------------------------------------------------------------

#define U16P(x) ((u16*)&(x))

// Returns the hiword of a 32 bit integer.
#define U16P_HI(x) (((u16*)&(x)) + 1)

extern u16* regtable[0x401];
extern u16 const* const regtable_original[0x401];
